package com.kunlun.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.kunlun.common.model.Page;
import com.kunlun.common.model.ResponseMessage;
import com.kunlun.common.model.monitor.SystemDataModel;
import com.kunlun.common.utils.CalculateUtil;
import com.kunlun.common.utils.JsonUtil;
import com.kunlun.system.config.dataSource.DataSourceType;
import com.kunlun.system.config.dataSource.DbContextHolder;
import com.kunlun.system.dao.ISystemMachineDao;
import com.kunlun.system.model.DictionaryValueModel;
import com.kunlun.system.model.SystemInstanceModel;
import com.kunlun.system.model.SystemMachineModel;
import com.kunlun.system.model.vo.MachineInstanceVo;
import com.kunlun.system.service.IDictionaryService;
import com.kunlun.system.service.ISystemInstanceService;
import com.kunlun.system.service.ISystemMachineService;
import com.kunlun.system.utils.CommonUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class SystemMachineService implements ISystemMachineService {

    private static Logger log = LogManager.getLogger();

    private static final String MONITOR_URL_SUFFIX = "/commonApi/monitorSystem";

    @Value("${kunlun.gateWayUrl}")
    private String gateWayUrl;

    @Autowired
    private ISystemMachineDao systemMachineDao;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IDictionaryService dictionaryService;
    @Autowired
    private ISystemInstanceService systemInstanceService;

    @Override
    public Page<MachineInstanceVo> getAllMachine(SystemMachineModel machineModel, int currentPage, int pageSize) throws Exception {
        int startIndex = (currentPage - 1) * pageSize;
        Map<String, Object> queryMap = CommonUtil.packageQueryMap(machineModel, startIndex, pageSize);

        DbContextHolder.setDbType(DataSourceType.MASTER.getKey());

        int count = systemMachineDao.selectMachineCount(queryMap);
        List<MachineInstanceVo> machineModels = systemMachineDao.getMachineInstance(queryMap);

        Page<MachineInstanceVo> page = new Page<>();
        page.setCurrentPage(currentPage);
        page.setPageSize(pageSize);
        page.setTotal(count);
        page.setRecords(machineModels);
        return page;
    }

    @Override
    public void downloadTemplate(HttpServletRequest request, HttpServletResponse response, String type) throws Exception{
        String templatePath = null;
        if ("machine".equals(type)) {
            templatePath = "D:\\template\\machine_template.xlsx";
            exportTemplate(response, templatePath);
        } else {
            templatePath = System.getProperty("user.dir");
            exportTemplate(response, templatePath);
        }
    }

    @Override
    public void collectMonitor() throws Exception {
        List<SystemMachineModel> systemMachineModels = new ArrayList<>();
        List<SystemInstanceModel> systemInstanceModels = new ArrayList<>();
        List<DictionaryValueModel> dictValues = dictionaryService.getValuesByDictCode("systemService");
        try {
            for (DictionaryValueModel dictValue : dictValues) {
                log.info("monitoring service ===>>> " + dictValue.getDictSubCode());
                String url = gateWayUrl + dictValue.getDictSubCode() + MONITOR_URL_SUFFIX;
                log.info("ScheduleMonitorTask url => " + url);
                ResponseMessage responseMessage = restTemplate.getForObject(url, ResponseMessage.class);
                SystemDataModel systemData = JSONObject.parseObject(JsonUtil.toJsonString(responseMessage.getData()), SystemDataModel.class);
                log.info("ScheduleMonitorTask systemData => " + JsonUtil.toJsonString(systemData));

                SystemMachineModel systemMachineModel = new SystemMachineModel(systemData);
                systemMachineModels.add(systemMachineModel);
                SystemInstanceModel systemInstanceModel = new SystemInstanceModel(systemData);
                systemInstanceModel.setMachineId(systemMachineModel.getId());
                systemInstanceModels.add(systemInstanceModel);
            }
        } catch (Exception e) {
            log.error("collectMonitor error: ", e);
        } finally {
            systemMachineDao.addSystemMachine(systemMachineModels);
            systemInstanceService.addSystemInstance(systemInstanceModels);
        }
    }

    @Override
    public MachineInstanceVo getMachineLineData(String id) throws Exception {
        MachineInstanceVo vo = systemMachineDao.getMachineLineData(id);
        vo.setCpuUsedPercent(CalculateUtil.calculate("a * b", 2, vo.getCpuUsedPercent(), "100"));
        vo.setMemoryUsedPercent(CalculateUtil.calculate("a * b", 2, vo.getMemoryUsedPercent(), "100"));
        vo.setDiskUsedPercent(CalculateUtil.calculate("a * b", 2, vo.getDiskUsedPercent(), "100"));
        vo.setJvmUsedPercent(CalculateUtil.calculate("a * b", 2, vo.getJvmUsedPercent(), "100"));
        String jvmUpTime = CalculateUtil.calculate("a / b", 0, String.valueOf(vo.getJvmUpTime()), "1000");
        vo.setJvmUpTime(Long.valueOf(jvmUpTime));
        return vo;
    }

    @Override
    public List<MachineInstanceVo> getSystemMonitorData(String serviceName, String ipAddress, Integer pageSize) throws Exception {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("serviceName", serviceName);
        queryMap.put("ipAddress", ipAddress);
        queryMap.put("currentPage", 1);
        queryMap.put("pageSize", pageSize);
        List<MachineInstanceVo> machineModels = systemMachineDao.getMachineInstance(queryMap);
        machineModels = machineModels.stream().filter(obj -> !ObjectUtils.isEmpty(obj.getCreateTime())).map(model -> {
            model.setCpuUsedPercent(CalculateUtil.calculate("a * b", 2, model.getCpuUsedPercent(), "100"));
            model.setMemoryUsedPercent(CalculateUtil.calculate("a * b", 2, model.getMemoryUsedPercent(), "100"));
            model.setDiskUsedPercent(CalculateUtil.calculate("a * b", 2, model.getDiskUsedPercent(), "100"));
            model.setJvmUsedPercent(CalculateUtil.calculate("a * b", 2, model.getJvmUsedPercent(), "100"));
            return model;
        }).sorted(Comparator.comparing(MachineInstanceVo::getCreateTime)).collect(Collectors.toList());
        return machineModels;
    }

    private void exportTemplate(HttpServletResponse response, String templatePath) throws Exception {
        OutputStream os = response.getOutputStream();
        InputStream is = new FileInputStream(templatePath);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss");
        String fileName = dateFormat.format(new Date()) + ".xlsx";

        response.addHeader("content-disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "utf-8"));
        byte[] bytes = new byte[4096];
        int size = is.read(bytes);
        while (size > 0) {
            os.write(bytes, 0, size);
            size = is.read(bytes);
        }
        os.close();
        is.close();
    }
}
